﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.DirectoryServices;
using System.Linq;
using System.Text;

namespace SO.Utilities.ActiveDirectory
{
    public class ADAccess
    {
        public static List<ADUser> GetUsersInGroup(string domain, string path, string group)
        {
            return GetUsersInADGroup(domain, path, group);   
        }

        public static List<ADUser> GetUsersInGroup(string group)
        {
            return GetUsersInLocalGroup(group);
        }

        private static List<ADUser> GetUsersInLocalGroup(string group)
        {
            var userList = new List<ADUser>();

            try
            {
                DirectoryEntry groupEntry = new DirectoryEntry(string.Format("WinNT://./{0},group", group));
                DirectoryEntry memberEntry;
                ADUser tempUser;

                foreach (object member in (IEnumerable)groupEntry.Invoke("Members"))
                {
                    tempUser = new ADUser();
                    memberEntry = new DirectoryEntry(member);

                    tempUser.Name = memberEntry.Properties["name"].Value.ToString();
                    tempUser.sAMAccountName = memberEntry.Properties["sAMAccountName"].Value.ToString();
                    tempUser.UserAccountControl = int.Parse(memberEntry.Properties["UserAccountControl"].Value.ToString());
                    tempUser.UserPrincipalName = memberEntry.Properties["userPrincipalName"].Value.ToString();

                    userList.Add(tempUser);
                }                
            }
            catch (Exception ex)
            {
                throw new Exception("Error reading users in local group", ex);
            }

            return userList;
        }

        private static List<ADUser> GetUsersInADGroup(string domain, string path, string group)
        {
            var userList = new List<ADUser>();

            DirectoryEntry de = new DirectoryEntry(string.Format("LDAP://{0}", domain));

            DirectorySearcher ds = new DirectorySearcher(de, "(objectClass=person)");
            ds.Filter = string.Format("(memberOf=CN={0},{1},{2})", group, path, domain);

            ds.PropertiesToLoad.Add("givenname");
            ds.PropertiesToLoad.Add("cn");
            ds.PropertiesToLoad.Add("userAccountControl");
            ds.PropertiesToLoad.Add("displayName");
            ds.PropertiesToLoad.Add("dn");
            ds.PropertiesToLoad.Add("givenName");
            ds.PropertiesToLoad.Add("mail");
            ds.PropertiesToLoad.Add("name");
            ds.PropertiesToLoad.Add("sAMAccountName");
            ds.PropertiesToLoad.Add("sn");

            ADUser temp;

            foreach (SearchResult sr in ds.FindAll())
            {
                try
                {
                    temp = new ADUser();

                    temp.CN = sr.Properties["cn"].ToString();
                    temp.DisplayName = sr.Properties["displayName"].ToString();
                    temp.DN = sr.Properties["dn"].ToString();
                    temp.GivenName = sr.Properties["givenName"].ToString();
                    temp.Mail = sr.Properties["mail"].ToString();
                    temp.Name = sr.Properties["name"].ToString();
                    temp.sAMAccountName = sr.Properties["sAMAccountName"].ToString();
                    temp.SN = sr.Properties["sn"].ToString();
                    temp.UserAccountControl = int.Parse(sr.Properties["userAccountControl"].ToString());
                    temp.UserPrincipalName = sr.Properties["UserPrincipalName"].ToString();
                    
                    userList.Add(temp);
                }
                catch (Exception ex)
                {
                }
            }

            return userList;
        }
    }
}
